package main

import (
	"flag"
	"net"
	"os"
	"fmt"
)

var maxReadOnceSize = 10

var defaultHost = "127.0.0.1"

var defaultPort = "843"

var request = []byte("<policy-file-request/>")
var welcome = []byte("<?xml version=\"1.0\"?><!DOCTYPE cross-domain-policySYSTEM \"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\"><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\" /></cross-domain-policy>")

/**
 *
 * Just prints out the msg length and msg contents for now.
 *
 * Note that if you use telnet to test this, '\r' and \'n' 
 * will not be filtered out but printed on the screen.
 *
 */
func handleMsg(length int, err os.Error, msg []byte) {

	if length > 0 {

		print("<", length, ":")

		for i := 0; ; i++ {
			if msg[i] == 0 {
				break
			}
			fmt.Printf("%c", msg[i])
		}
		println(">")
	}
}

func sayHello(to net.Conn) {

	wrote, err := to.Write(welcome)

	if err != nil {
		println("Wrote ", wrote, " bytes.")
		println("Write: ", err.String())
	}
}

func connectionHandler(connection net.Conn) {

	connFrom := connection.RemoteAddr().String()

	println("Connection from: ", connFrom)

	//sayHello(connection)
	for {
		var ibuf []byte = make([]byte, maxReadOnceSize+1)
		length, err := connection.Read(ibuf[0:maxReadOnceSize])
		ibuf[maxReadOnceSize] = 0 // prevent overflow

		switch err {
		case nil:
			handleMsg(length, err, ibuf)
			sayHello(connection)
			goto DISCONNECT
		case os.EAGAIN:
			continue
		default:
			goto DISCONNECT
		}

	}
DISCONNECT:

	err := connection.Close()

	if err != nil {
		println("Close: ", err.String())
	}

	println("Closed connection: ", connFrom)

}

func initServer(hostAndPort string) (l *net.TCPListener) {

	serverAddr, err := net.ResolveTCPAddr("tcp", hostAndPort)

	if err != nil {
		println("Resolving address:port failed: `", hostAndPort, "'")
	}

	listener, err := net.ListenTCP("tcp", serverAddr)

	if err != nil {
		println("ListenTCP: ", err.String())
	}

	println("Listening to:    ", listener.Addr().String())

	return listener
}

func ReadCrossFile(filename string) (string, os.Error) {
	f, err := os.Open(filename)
	if err != nil {
		return "", err
	}
	defer f.Close() // f.Close will run when we're finished.

	var result []byte
	buf := make([]byte, 100)
	for {
		n, err := f.Read(buf[0:])
		result = append(result, buf[0:n]...) // append is discussed later.
		if err != nil {
			if err == os.EOF {
				break
			}
			return "", err // f will be closed if we return here.
		}
	}
	return string(result), nil // f will be closed if we return here.
}

func main() {

	flag.Parse()
	if flag.NArg() >= 2 {
		defaultHost = flag.Arg(0)
		defaultPort = flag.Arg(1)
	}
	println("usage: host port")

	filepath := "crossfile"
	if flag.NArg() > 2 {
		filepath = flag.Arg(2)
	}

	content, err := ReadCrossFile(filepath)
	if err == nil {
		welcome = []byte(content)
	}
	println("usage corss: \n" + string(welcome))

	hostAndPort := fmt.Sprintf("%s:%s", defaultHost, defaultPort)

	listener := initServer(hostAndPort)

	for {
		connection, err := listener.Accept()

		if err != nil {
			println("Accept: ", err.String())
		}

		go connectionHandler(connection)
	}
	
}
